﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Globalization;
using System.Windows.Forms;
using System.Diagnostics.Contracts;

namespace RPNCalculator
{
    public partial class RPNCalculator : Form
    {
        private Dictionary<string, int> Notations = new Dictionary<string, int>();
        private Stack<int> ValueStack = new Stack<int>();
        private Stack<Command> UndoStack = new Stack<Command>();


        public RPNCalculator()
        {
            InitializeComponent();

            //Add 4 operators into the notations
            Notations.Add("Dec", 10);
            Notations.Add("Bin", 2);
            Notations.Add("Oct", 8);
            Notations.Add("Hex", 16);

            //Add notations to combobox and set decimal as default
            comboBoxNotation.Items.AddRange(Notations.Keys.ToArray());
            comboBoxNotation.SelectedIndex = 0;
        }

        
        //pre: blah blah
        private void LoadGUI()
        {
            listBoxNumbers.Items.Clear();

            //Add values from ValueStack with specific notation system
            int Notation = Notations[comboBoxNotation.Text];
            foreach(int i in ValueStack)
                listBoxNumbers.Items.Insert(listBoxNumbers.Items.Count, Convert.ToString(i, Notation));
            
            // Clear textbox
            textBoxValue.Clear();
           
            // Enable buttons
            buttonAdd.Enabled = AddCommand.IsExecutable(ValueStack.Count);
            buttonSubtract.Enabled = SubtractCommand.IsExecutable(ValueStack.Count);
            buttonMultiply.Enabled = MultiplyCommand.IsExecutable(ValueStack.Count);
            buttonDivide.Enabled = DivideCommand.IsExecutable(ValueStack.Count);
            buttonSumma.Enabled = SummaCommand.IsExecutable(ValueStack.Count);
            buttonMul.Enabled = MulCommand.IsExecutable(ValueStack.Count);
            buttonUndo.Enabled = UndoStack.Count > 0;
            buttonEnter.Enabled = false;
           
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            LoadGUI();
        }


        private void buttonClear_Click(object sender, EventArgs e)
        {
            UndoStack.Clear();
            ValueStack.Clear();
            LoadGUI();
        }

        //changes the number representation of the listbox content to whatever notation is chosen.
        //pre: true
        //post: listnumbers.numbers[0...count-1].NumberValues=listnumbers.numbers[0...count-1].NumberValues
        private void comboBoxNotation_SelectedIndexChanged(object sender, EventArgs e)
        {
            //Refresh GUI when notation is changed
            LoadGUI();          
        }

        private void textBoxNumber_TextChanged(object sender, EventArgs e)
        {
            buttonEnter.Enabled = textBoxValue.Text != "";
        }


        private void buttonUndo_Click(object sender, EventArgs e)
        {
            //Pop previous command and undo it when button is clicked
            Contract.Requires(this.UndoStack.Count > 0);
            UndoStack.Pop().Undo(); 
            LoadGUI();
        }

        private void ExecuteCommand(Command cmd)
        {
            //Execute command 
            cmd.Execute();
            //Push every command to UndoStack 
            UndoStack.Push(cmd);   
            LoadGUI();
        }

        private void buttonEnter_Click(object sender, EventArgs e)
        {
            try
            {
                // Show the selected notation system
                int Notation = Notations[comboBoxNotation.Text];
                // Convert entered value to decimal value
                int Value = Convert.ToInt32(textBoxValue.Text, Notation);
                ExecuteCommand(new PushCommand(ValueStack, Value));             
            }
            catch
            {
                MessageBox.Show("invalid input.");
            }
        }

        private void buttonAdd_Click(object sender, EventArgs e)
        {
            ExecuteCommand(new AddCommand(ValueStack));
        }

        private void buttonSubtract_Click(object sender, EventArgs e)
        {
            ExecuteCommand(new SubtractCommand(ValueStack));
        }

        private void buttonMultiply_Click(object sender, EventArgs e)
        {
            ExecuteCommand(new MultiplyCommand(ValueStack));
        }

        private void buttonDivide_Click(object sender, EventArgs e)
        {
            ExecuteCommand(new DivideCommand(ValueStack));
        }

        private void buttonSumma_Click(object sender, EventArgs e)
        {
            ExecuteCommand(new SummaCommand(ValueStack));
        }
  
        private void buttonMul_Click(object sender, EventArgs e)
        {
            ExecuteCommand(new MulCommand(ValueStack));
        }

    
    }
}
